#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include "ManejadorSemAscensores.h"
#include "Semaforo.h"
#include "Constantes.h"
#include "Logger.h"
#include "Util.h"

#define PROCESS_NAME "MANEJADOR_SEM_ASCENSOR"

using namespace std;

void ManejadorSemAscensores::log(string message) {
	string name = PROCESS_NAME;
	string msg = name + ": " +  message;
	logger->loggearLog(msg);
}

void ManejadorSemAscensores::sync(string message) {
	string name = PROCESS_NAME;
	string msg = name + ": " +  message;
	logger->loggearSynchro(msg);
}

void ManejadorSemAscensores::debug(string message) {
	string name = PROCESS_NAME;
	string msg = name + ": " +  message;
	logger->loggearDebug(msg);
}

ManejadorSemAscensores::ManejadorSemAscensores(int cantAscensores)
{
	this->logger = Logger::getInstance();

	this->cantAscensores = cantAscensores;

	this->crearSemaforos();
}

ManejadorSemAscensores::~ManejadorSemAscensores() {

	for (int i = 0; i < this->cantAscensores; i++) {
		delete(this->semAscensores[i]);
	}
	this->sync("Semáforos por Ascensor destruidos");

	this->sync("Liberamos la memoria del Ascensor");
	free(this->semAscensores);

}

void ManejadorSemAscensores::crearSemaforos(){

	this->semAscensores = (Semaforo**) malloc(sizeof (Semaforo*) * this->cantAscensores);
	for (int i = 0; i < this->cantAscensores; i++) {
		this->semAscensores[i] = new Semaforo((char*) SEM_ARCHIVO_ASC_OUT, (char) i,
				SEM_ASC_OUT_CANTIDAD);
	}
	this->sync("Semáforos para ascensores creados.");
}

void ManejadorSemAscensores::inicializar() {
	int valoresIniciales[this->cantAscensores];
	for (int i = 0; i < this->cantAscensores; i++){
		valoresIniciales[i] = 0;
	}
	for (int i = 0; i < this->cantAscensores; i++)
		this->semAscensores[i]->inicializar(valoresIniciales);
	this->sync("Semáforos por ascensor inicializados.");
}

void ManejadorSemAscensores::liberarSemaforos() {
	for (int i = 0; i < this->cantAscensores; i++) {
		this->semAscensores[i]->eliminar_todos();
	}
	this->sync("Semáforos por ascensor liberados.");
}

void ManejadorSemAscensores::esperarApertura(int numAsc){
	this->sync("P---> Sem Ascensor = SEM_OPEN" );
	this->semAscensores[numAsc]->p(SEM_OPEN,1);
}

void ManejadorSemAscensores::esperarProxPisos(int numAsc){
	this->sync("P---> Sem Ascensor = SEM_NEXT_STOP");
	this->semAscensores[numAsc]->p(SEM_NEXT_STOP,1);
}

void ManejadorSemAscensores::abrir(int numAsc,int cantidad){
	this->sync("V---> Sem Ascensor = SEM_OPEN  en cantidad " + Util::intToString(cantidad));
	this->semAscensores[numAsc]->v(SEM_OPEN,cantidad);
	this->sync("P---> Sem Ascensor = SEM_CLOSE en cantidad " + Util::intToString(cantidad));
	this->semAscensores[numAsc]->p(SEM_CLOSE,cantidad);
}

void ManejadorSemAscensores::habilitarCierre(int numAsc){
	this->sync("V---> Sem Ascensor = SEM_CLOSE");
	this->semAscensores[numAsc]->v(SEM_CLOSE,1);
	this->sync("P---> Sem Ascensor = SEM_ALL_NOTIFIED");
	this->semAscensores[numAsc]->p(SEM_ALL_NOTIFIED,1);
}

void ManejadorSemAscensores::cerrar(int numAsc, int cantidad){
	this->sync("V---> Sem Ascensor = SEM_ALL_NOTIFIED en cantidad " + Util::intToString(cantidad));
	this->semAscensores[numAsc]->v(SEM_ALL_NOTIFIED,cantidad);
}

void ManejadorSemAscensores::despertarAscensor(int numAsc){
	this->sync("V---> Sem Ascensor = SEM_NEXT_STOP");
	this->semAscensores[numAsc]->v(SEM_NEXT_STOP,1);
}
